#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QFileDialog>
#include <QDateTime>
#include <QString>
#include <QTextStream>
#include <QMetaType>
#include <QDebug>
//#include <QThread>
#include "asyncfilebuffer.h"

const int msecInt = 200;

MainWindow::MainWindow(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::MainWindow),
    fb(new AsyncFileBuffer),
    pl(new ProgressListener(fb, msecInt)),
    infoWindow(pl, fb),
    logStream(&logMsg)
{
    ui->setupUi(this);        
    connect(fb, SIGNAL(fileLoaded(QString,qint64)), SLOT(onFileLoaded(QString,qint64)));
    connect(fb, SIGNAL(fileLoadingError(QString,QString,IFileBuffer::State)), SLOT(onFileLoadingError(QString,QString,IFileBuffer::State)));
    connect(fb, SIGNAL(fileSaved(QString)), SLOT(onFileSaved(QString)));
    connect(fb, SIGNAL(fileSavingError(QString,QString)), SLOT(onFileSavingError(QString,QString)));
    connect(fb, SIGNAL(dataCleared()), SLOT(onDataCleared()));
    setStatusFree();
}

MainWindow::~MainWindow()
{
    delete ui;
    delete pl;
    fb->stop();
//    fb->getLastError();
    delete fb;
}

void MainWindow::log(QString msg)
{
    QString line = QDateTime::currentDateTime().toString();
    QTextStream s(&line);
    s << " " << msg /*<< endl*/;
    ui->logger->append(line);
}

QTextStream& MainWindow::logBegin()
{
//    qDebug() << "QTextStream& MainWindow::logBegin()";
//    qDebug() << "logMsg:" << logMsg;
    return logStream;
}

QString MainWindow::logEnd()
{
//    qDebug() << "QString MainWindow::logEnd()";
//    qDebug() << "logMsg:" << logMsg;
    return QString();
}

const int BYTES_IN_MB = 1024 * 1024;

void MainWindow::on_loadFile_clicked()
{
    QString error = fb->holdLoad();
    if(error.isNull()){
        QString fName = QFileDialog::getOpenFileName(this);
        if(!fName.isNull()){
            QString status = tr("Загрузка файла");
            ui->statusEdit->setText(status);
            log(status + ": " + fName);
            fb->loadFile(fName);
        } else {
            log(tr("Загрузка файла отменена пользователем"));
            fb->release();
        }
    } else {
        logMsg.clear();
        logBegin() << tr("Невозможно начать процесс загрузки файла по причине:") << endl
                   << error << logEnd();
        log(logMsg);
    }
}

void MainWindow::onFileLoaded(QString fileName, qint64 fileSize)
{
//    qDebug() << "void MainWindow::onFileLoaded(QString fileName, qint64 fileSize)";
//    qDebug() << "in thread" << thread()->currentThreadId();
    log(tr("Загрузка файла %1 успешно завершена").arg(fileName));
    setStatusLoaded(fileSize);
}

void MainWindow::onFileLoadingError(QString fileName, QString error, IFileBuffer::State newState)
{
//    qDebug() << "void MainWindow::onFileLoadingError(QString fileName, QString error, IFileBuffer::State newState)";
//    qDebug() << "error:" << error;
    logMsg.clear();
    logBegin() << tr("Ошибка при загрузке файла ") << fileName << endl
               << error << logEnd();
    log(logMsg);
//    updateStatus();    
    if(newState == IFileBuffer::FREE){
        setStatusFree();
    }
}

void MainWindow::on_saveFile_clicked()
{
    QString error = fb->holdSave();
    if(error.isNull()){
        QString fName = QFileDialog::getSaveFileName(this);
        if(!fName.isNull()){            
            QString status = tr("Сохранение файла");
            ui->statusEdit->setText(status);
            log(status + ": " +fName);
            fb->saveFile(fName);
        } else {
            log(tr("Сохранение файла отменено пользователем"));
            fb->release();
        }
    } else {
        logMsg.clear();
        logBegin() << tr("Невозможно начать процесс сохранения файла по причине:") << endl
                   << error << logEnd();
        log(logMsg);
    }
}

void MainWindow::onFileSaved(QString fileName)
{
    log(tr("Файл %1 успешно сохранен").arg(fileName));
    updateStatus();
}

void MainWindow::onFileSavingError(QString fileName, QString error)
{
//    qDebug() << "void MainWindow::onFileSavingError(QString fileName, QString error)";
//    qDebug() << "error:" << error;
    logMsg.clear();
    logBegin() << tr("Ошибка при сохранении файла ") << fileName << endl
               << error << logEnd();
    log(logMsg);
    updateStatus();
}

void MainWindow::on_clearBuffer_clicked()
{
    QString error = fb->holdClear();
    if(error.isNull()){
        fb->clearData();
    } else {
        logMsg.clear();
        logBegin() << tr("Невозможно начать процесс очистки памяти по причине:") << endl
                   << error << logEnd();
        log(logMsg);
    }
}

void MainWindow::onDataCleared()
{
    log(tr("Память очищена"));
    setStatusFree();
}

void MainWindow::on_clearLog_clicked()
{
    ui->logger->clear();
}

void MainWindow::updateStatus()
{
    switch (fb->getState())
    {
        case IFileBuffer::FREE:
            setStatusFree();
            break;
        case IFileBuffer::LOADED:
            setStatusLoaded(fb->getFileSize());
            break;
        default:
            break;
    }
}

void MainWindow::setStatusFree()
{
    ui->statusEdit->setText(tr("Файл не загружен"));
}

void MainWindow::setStatusLoaded(qint64 fileSize)
{
    ui->statusEdit->setText(tr("Загружен файл размера %1 байт").arg(fileSize));
}
